package com.lyun.common;

import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class RedisGeoUtils {

    @Resource
    private RedisTemplate<String, String> redisTemplate;

    private final static double EARTH_RADIUS = 6378.137;


    public List<Map<String, Object>> getOthers(String key, Point point, Integer distance) {

        Circle circle = new Circle(point, new Distance(distance, Metrics.KILOMETERS));
        RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs();

        //limit 获取几个坐标
        args.sortAscending()
                .includeCoordinates()
                .includeDistance()
                .limit(10);

        //.radius 执行查询
        GeoResults<RedisGeoCommands.GeoLocation<String>> geo = redisTemplate.boundGeoOps(key).radius(circle, args);

        List<Map<String, Object>> list = new ArrayList<>();
        Map<String, Object> map = new HashMap<>(16);
        for (GeoResult<RedisGeoCommands.GeoLocation<String>> result : geo) {
            RedisGeoCommands.GeoLocation<String> location = result.getContent();
            // value
            Long id = Long.valueOf(location.getName());
            map.put("name", id);
            map.put("distance", result.getDistance());
            list.add(map);
        }
        return list;
    }

    public GeoResults<RedisGeoCommands.GeoLocation<String>> getMovementsRadius(Point point, Integer distance) {
        return redisTemplate.opsForGeo().radius(EveryConstant.REDIS_GEO_MOVEMENTS, new Circle(point, new Distance(distance, Metrics.KILOMETERS)));
    }

    public Map<String, Double> getDistanceMapByRadius(GeoResults<RedisGeoCommands.GeoLocation<String>> radius) {
        Map<String, Double> distanceMap = new HashMap<>();
        for (GeoResult<RedisGeoCommands.GeoLocation<String>> result : radius) {
            distanceMap.put(result.getContent().getName(), result.getDistance().getValue());
        }
        return distanceMap;
    }


    private static double rad(double d) {
        return d * Math.PI / 180.0;
    }

    public static String getDistance(Point point, Point toPoint) {
        //经度
        double longitude1 = rad(point.getX());
        double longitude2 = rad(toPoint.getX());
        double a = longitude1 - longitude2;

        double b = rad(point.getY()) - rad(toPoint.getY());
        double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(longitude1) * Math.cos(longitude2) * Math.pow(Math.sin(b / 2), 2)));
        s = s * EARTH_RADIUS;

        // 除10000   km
        // 除10      m
        s = (s * 10000) / 10000;
        DecimalFormat df = new DecimalFormat("#.00");

        if (s > 1) {
            double result = Double.parseDouble(df.format(s));
            return result + "公里";
        }
        s = s * 1000;
        double result = Double.parseDouble(df.format(s));
        return result + "米";
    }
}
